/**
 * @p.md
 * 
 * WASM 桥接器，提供 TypeScript 和 Go ProtoActor 之间的通信
 */

import { WasmEventListener, WasmEventManager, WasmEventManagerFactory, WasmEventType } from './wasmEvents';

/**
 * 回调函数类型
 */
type WasmCallback = (result: any) => void;

/**
 * WASM 桥接接口
 */
export interface WasmBridge {
  /**
   * 初始化 WASM 模块
   * @param wasmPath WASM 文件路径，默认为 './protoactor.wasm'
   */
  initialize(wasmPath?: string): Promise<void>;
  
  /**
   * 调用 Go 函数
   * @param funcName 函数名
   * @param args 函数参数
   * @returns 函数返回值的 Promise
   */
  invokeGoFunction<T = any>(funcName: string, ...args: any[]): Promise<T>;
  
  /**
   * 注册可被 Go 调用的 TypeScript 函数
   * @param funcName 函数名
   * @param func 函数实现
   */
  registerTSFunction(funcName: string, func: (...args: any[]) => any): void;
  
  /**
   * 创建回调
   * @param callback 回调函数
   * @returns 回调 ID
   */
  createCallback(callback: WasmCallback): number;
  
  /**
   * 调用回调
   * @param callbackId 回调 ID
   * @param result 回调结果
   */
  invokeCallback(callbackId: number, result: any): void;
  
  /**
   * 添加事件监听器
   * @param eventType 事件类型
   * @param listener 监听器函数
   */
  addEventListener(eventType: WasmEventType, listener: WasmEventListener): void;
  
  /**
   * 移除事件监听器
   * @param eventType 事件类型
   * @param listener 监听器函数
   */
  removeEventListener(eventType: WasmEventType, listener: WasmEventListener): void;
}

/**
 * WASM 桥接器实现
 */
class WasmBridgeImpl implements WasmBridge {
  private static instance: WasmBridgeImpl;
  private initialized: boolean = false;
  private wasmInstance: WebAssembly.Instance | null = null;
  private goInstance: any = null;
  private callbacks: Map<number, WasmCallback> = new Map();
  private nextCallbackId: number = 1;
  private tsFunctions: Map<string, (...args: any[]) => any> = new Map();
  private eventManager: WasmEventManager;
  
  /**
   * 私有构造函数，使用 getInstance 方法获取实例
   */
  private constructor() {
    // 初始化事件管理器
    this.eventManager = WasmEventManagerFactory.getInstance();
    
    // 初始化空桥接对象
    this.setupTSBridge();
  }
  
  /**
   * 获取 WasmBridge 单例
   */
  public static getInstance(): WasmBridgeImpl {
    if (!WasmBridgeImpl.instance) {
      WasmBridgeImpl.instance = new WasmBridgeImpl();
    }
    return WasmBridgeImpl.instance;
  }
  
  /**
   * 设置 TypeScript 桥接对象，供 Go 代码调用
   */
  private setupTSBridge(): void {
    // @ts-ignore - 全局变量
    if (typeof globalThis !== 'undefined') {
      // @ts-ignore - 全局变量
      globalThis.__TS_BRIDGE__ = {
        invokeTS: (funcName: string, argsJson: string) => {
          const func = this.tsFunctions.get(funcName);
          if (func) {
            try {
              // 解析参数
              const args = argsJson ? JSON.parse(argsJson) : [];
              // 调用函数
              const result = func(...args);
              
              // 触发消息接收事件
              this.eventManager.dispatchEvent(WasmEventType.MESSAGE_RECEIVED, {
                functionName: funcName,
                args: args
              });
              
              // 序列化结果
              return typeof result === 'undefined' ? '' : JSON.stringify(result);
            } catch (error) {
              console.error(`调用 TS 函数 ${funcName} 失败:`, error);
              
              // 触发错误事件
              this.eventManager.dispatchEvent(WasmEventType.ERROR, {
                functionName: funcName,
                error: error
              });
              
              return JSON.stringify({ error: `${error}` });
            }
          }
          return '';
        }
      };
      
      // 添加回调注册表
      // @ts-ignore - 全局变量
      globalThis._callbackRegistry = this.callbacks;
    }
  }
  
  /**
   * 初始化 WASM 模块
   * @param wasmPath WASM 文件路径
   */
  public async initialize(wasmPath: string = './protoactor.wasm'): Promise<void> {
    if (this.initialized) {
      return;
    }
    
    // 检查环境
    if (typeof WebAssembly === 'undefined') {
      const error = new Error('当前环境不支持 WebAssembly');
      this.eventManager.dispatchEvent(WasmEventType.ERROR, { error });
      throw error;
    }
    
    // 检查 Go 类
    // @ts-ignore - Go 类由 wasm_exec.js 提供
    if (typeof Go === 'undefined') {
      const error = new Error('未找到 Go 类，请确保加载了 wasm_exec.js');
      this.eventManager.dispatchEvent(WasmEventType.ERROR, { error });
      throw error;
    }
    
    try {
      // 创建 Go 实例
      // @ts-ignore - Go 类
      this.goInstance = new Go();
      
      // 加载 WASM 模块
      const result = await WebAssembly.instantiateStreaming(
        fetch(wasmPath),
        this.goInstance.importObject
      );
      
      this.wasmInstance = result.instance;
      
      // 运行 WASM 模块
      this.goInstance.run(this.wasmInstance);
      
      this.initialized = true;
      console.log('ProtoActor WASM 模块初始化成功');
      
      // 触发初始化完成事件
      this.eventManager.dispatchEvent(WasmEventType.INITIALIZED, null);
    } catch (error) {
      console.error('初始化 WASM 模块失败:', error);
      
      // 触发错误事件
      this.eventManager.dispatchEvent(WasmEventType.ERROR, { error });
      
      throw error;
    }
  }
  
  /**
   * 调用 Go 函数
   * @param funcName 函数名
   * @param args 函数参数
   * @returns 函数返回值的 Promise
   */
  public async invokeGoFunction<T = any>(funcName: string, ...args: any[]): Promise<T> {
    if (!this.initialized) {
      throw new Error('WASM 模块尚未初始化');
    }
    
    // 序列化参数
    const argsJson = JSON.stringify(args);
    
    try {
      // @ts-ignore - Go 导出的函数
      const resultJson = globalThis.invokeGoFunction(funcName, argsJson);
      
      // 解析结果
      const result = JSON.parse(resultJson);
      
      // 检查错误
      if (result && result.error) {
        throw new Error(result.error);
      }
      
      // 为特定函数触发特定事件
      if (funcName === 'createActor') {
        this.eventManager.dispatchEvent(WasmEventType.ACTOR_CREATED, result);
      } else if (funcName === 'stopActor') {
        this.eventManager.dispatchEvent(WasmEventType.ACTOR_STOPPED, result);
      }
      
      return result;
    } catch (error) {
      console.error(`调用 Go 函数 ${funcName} 失败:`, error);
      
      // 触发错误事件
      this.eventManager.dispatchEvent(WasmEventType.ERROR, {
        functionName: funcName,
        error: error
      });
      
      throw error;
    }
  }
  
  /**
   * 注册可被 Go 调用的 TypeScript 函数
   * @param funcName 函数名
   * @param func 函数实现
   */
  public registerTSFunction(funcName: string, func: (...args: any[]) => any): void {
    this.tsFunctions.set(funcName, func);
  }
  
  /**
   * 创建回调
   * @param callback 回调函数
   * @returns 回调 ID
   */
  public createCallback(callback: WasmCallback): number {
    const id = this.nextCallbackId++;
    this.callbacks.set(id, callback);
    return id;
  }
  
  /**
   * 调用回调
   * @param callbackId 回调 ID
   * @param result 回调结果
   */
  public invokeCallback(callbackId: number, result: any): void {
    const callback = this.callbacks.get(callbackId);
    if (callback) {
      callback(result);
    }
  }
  
  /**
   * 添加事件监听器
   * @param eventType 事件类型
   * @param listener 监听器函数
   */
  public addEventListener(eventType: WasmEventType, listener: WasmEventListener): void {
    this.eventManager.addEventListener(eventType, listener);
  }
  
  /**
   * 移除事件监听器
   * @param eventType 事件类型
   * @param listener 监听器函数
   */
  public removeEventListener(eventType: WasmEventType, listener: WasmEventListener): void {
    this.eventManager.removeEventListener(eventType, listener);
  }
}

/**
 * WasmBridge 工厂
 */
export class WasmBridgeFactory {
  /**
   * 获取 WasmBridge 单例
   */
  public static getInstance(): WasmBridge {
    return WasmBridgeImpl.getInstance();
  }
} 